package com.q3d.demo.common.lib.context;

import java.util.Map;

import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component /** 注入组件 */
/**
 * 手动注入 Bean 所需要的上下文工具
 * 
 * @author 叶湘 ( weixin:yexiang841, email:yexiang841@qq.com )
 */
public class ApplicationContextUtil implements ApplicationContextAware {
  private static ApplicationContext applicationContext;

  /**
   * 实现 ApplicationContextAware 接口的 context 注入函数, 将其存入静态变量
   */
  public void setApplicationContext(ApplicationContext applicationContext) {
    if (ApplicationContextUtil.applicationContext == null) {
      ApplicationContextUtil.applicationContext = applicationContext;
    }
  }

  /**
   * 取得存储在静态变量中的 ApplicationContext
   */
  public static ApplicationContext getApplicationContext() {
    checkApplicationContext();
    return applicationContext;
  }

  /**
   * 清除 applicationContext 静态变量
   */
  public static void cleanApplicationContext() {
    applicationContext = null;
  }

  /**
   * 检查 applicationContext 注入
   */
  private static void checkApplicationContext() {
    if (applicationContext == null) {
      throw new IllegalStateException("applicaitonContext 未注入,请在 applicationContext.xml 中定义 SpringContextHolder");
    }
  }

  /**
   * 从静态变量 ApplicationContext 中取得 Bean，自动转型为所赋值对象的类型
   */
  @SuppressWarnings(value = "unchecked")
  public static <T> T getBean(String name) {
    checkApplicationContext();
    return (T) applicationContext.getBean(name);
  }

  /**
   * 从静态变量 ApplicationContext 中取得 Bean, 自动转型为所赋值对象的类型
   */
  @SuppressWarnings(value = "unchecked")
  public static <T> T getBean(Class<T> clazz) {
    checkApplicationContext();
    return (T) applicationContext.getBeansOfType(clazz);
  }

  /**
   * 从静态变量 ApplicationContext 中取得 Bean, 自动转型为所赋值对象 Map
   */
  public static <T> Map<String, T> getBeansOfType(Class<T> clazz){
      return applicationContext.getBeansOfType(clazz);
  }

}